package com.example.composableexample.animate

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.animateIntAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp

enum class UploadState {
    Normal,
    Start,
    Uploading,
    Success
}

@Preview
@Composable
fun UploadAnimation() {
    val originWidth by remember { mutableStateOf(180.dp) }
    val circleSize by remember { mutableStateOf(48.dp) }
    var uploadState by remember { mutableStateOf(UploadState.Normal) }
    var text by remember { mutableStateOf("Upload") }

    var textAlphaValue by remember { mutableStateOf(1f) }
    var backgroundColorValue by remember { mutableStateOf(Color.Blue) }
    var boxWidthValue by remember { mutableStateOf(originWidth) }
    var progressAlphaValue by remember { mutableStateOf(0f) }
    var progressValue by remember { mutableStateOf(0) }
    var clickEnabled by remember { mutableStateOf(true) }

    val textAlpha by animateFloatAsState(textAlphaValue)
    val backgroundColor by animateColorAsState(backgroundColorValue)
    val progressAlpha by animateFloatAsState(progressAlphaValue)
    val boxWidth by animateDpAsState(boxWidthValue) {
        // 按钮宽度变化完成监听，当状态为 Start 则修改为 Uploading
        if (uploadState == UploadState.Start) {
            uploadState = UploadState.Uploading
        }
    }
    val progress by animateIntAsState(progressValue) {
        // 进度完成监听，当状态为 Uploading 则修改为 Success
        if (uploadState == UploadState.Uploading) {
            uploadState = UploadState.Success
            // 文字内容修改为 Success
            text = "Success"
            clickEnabled = false
        }
    }

    // 界面布局
    Box(
        modifier = Modifier
            .padding(start = 10.dp, top = 10.dp)
            .width(originWidth),
        contentAlignment = Alignment.Center
    ) {
        // 按钮
        Box(
            modifier = Modifier
                .clip(RoundedCornerShape(circleSize / 2))
                .background(backgroundColor)
                .size(boxWidth, circleSize)
                .clickable(enabled = clickEnabled) {
                    // 点击时修改状态为开始上传
                    uploadState = UploadState.Start
                },
            contentAlignment = Alignment.Center,
        ) {
            // 进度
            Box(
                modifier = Modifier
                    .size(circleSize)
                    .clip(ArcShape(progress))
                    .alpha(progressAlpha)
                    .background(Color.Blue)
            )
            // 白色蒙版
            Box(
                modifier = Modifier
                    .size(40.dp)
                    .clip(RoundedCornerShape(20.dp))
                    .alpha(progressAlpha)
                    .background(Color.White)
            )
            // 文字
            Text(text, color = Color.White, modifier = Modifier.alpha(textAlpha))
        }
    }

    when (uploadState) {
        // 默认状态不处理
        UploadState.Normal -> {
        }
        // 开始上传
        UploadState.Start -> {
            // 文字透明度变为0
            textAlphaValue = 0f
            // 按钮背景颜色变为灰色
            backgroundColorValue = Color.Gray
            // 按钮宽度变为圆的宽度
            boxWidthValue = circleSize
            // 中间进度的透明度变为 1
            progressAlphaValue = 1f
        }
        // 上传中状态
        UploadState.Uploading -> {
            textAlphaValue = 0f
            backgroundColorValue = Color.Gray
            boxWidthValue = circleSize
            progressAlphaValue = 1f
            // 进度值变为 100
            progressValue = 100
        }
        // 上传完成
        UploadState.Success -> {
            // 文字透明度变为 1
            textAlphaValue = 1f
            // 颜色变为红色
            backgroundColorValue = Color.Red
            // 按钮宽度变化默认时的原始宽度
            boxWidthValue = originWidth
            // 进度透明度变为 0f
            progressAlphaValue = 0f
        }
    }
}

class ArcShape(private val progress: Int) : Shape {

    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val path = Path().apply {
            moveTo(size.width / 2f, size.height / 2f)
            arcTo(Rect(0f, 0f, size.width, size.height), -90f, progress / 100f * 360f, false)
            close()
        }
        return Outline.Generic(path)
    }
}


@Composable
fun AnimateDpBox() {
    var moveToRight by remember {
        mutableStateOf(false)
    }
    val startPadding = animateDpAsState(
        targetValue = if (moveToRight) 100.dp else 10.dp,
        finishedListener = {
            if (it == 100.dp) {
                moveToRight = false
            }
        }
    )

    Box(
        Modifier
            .padding(start = startPadding.value, top = 10.dp)
            .size(100.dp, 100.dp)
            .background(Color.Blue)
            .clickable {
                // 改变 moveToRight 状态，这里直接取反
                moveToRight = !moveToRight
            }
    )
}